//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#if _MSC_VER > 1000
#pragma once
#endif

#ifndef __GHOST_H__
#define __GHOST_H__

#include <elasys_server.h>
#include <linknode.h>
#include "aura.h"

#define Lock(hCritical)     do { \
                                AuraCriticalSection_Enter(hCritical); \
                            } while(0)

#define Unlock(hCritical)   do { \
                                AuraCriticalSection_Leave(hCritical); \
                            } while(0)

#define GHOST_HS_SLOTS 32
#define GHOST_HASHCODE(x) (x & (GHOST_HS_SLOTS - 1))

#define _GHOST_UNUSED()  do { assert(0); return E_NOT_IMPLEMENTED; } while(0)

class GhostFactory;
class Ghost: public DLinkNode {
public:
    virtual UInt32 AddRef()  = 0;
    virtual UInt32 Release() = 0;

    virtual oid_t  GetOid() const  { return m_oid;}
    virtual void SetOid(oid_t oid) { m_oid = oid; }
    virtual void DoAtException() { assert(0);   }

public:
    STATIC ECode S_Initialize();
    STATIC void  S_Destroy();

    STATIC ECode S_CreateGhost(
            /* [in] */ GhostFactory * pFactory,
            /* [out] */ Ghost ** ppGhost,
            /* [out] */ Boolean * pbExisted);

    STATIC ECode S_GetGhost(
            /* [in] */ GhostFactory * pFactory,
            /* [out] */ Ghost ** ppGhost);

    STATIC ECode S_DeleteGhost(
            /* [in] */ GhostFactory * pFactory,
            /* [in] */ Ghost * pGhost);

protected:
    Ghost(): m_oid(0) {}
private:
    oid_t m_oid;
};

class GhostFactory {
public:
    WString    GetName() { return m_name; }
    ObjectType GetType() { return m_type; }

public:
    virtual ECode CreateGhost(
            /* [out] */ Ghost ** ppGhost,
            /* [out] */ Boolean * pbExisted);

    virtual ECode GetGhost(
            /* [out] */ Ghost ** ppGhost);

    virtual ECode DeleteGhost(
            /* [in] */ Ghost * pGhost);

public:
    GhostFactory(WString name,
               ProcessId pid,
               GhostFactory* pConcreteFactory)
             : m_name(name), m_pid(pid),
               m_pConcreteFactory(pConcreteFactory) {}
    GhostFactory(oid_t oid): m_oid(oid) {}

protected:
    GhostFactory(WString name = NULL,
               ObjectType type = ObjectType_Invalid)
             : m_name(name), m_type(type) {}

private:
    WString    m_name;
    ObjectType m_type;
    ProcessId  m_pid;   // identifier of process sending request.
    oid_t        m_oid;
    GhostFactory * m_pConcreteFactory;
};

#endif //__GHOST_H__

